package net.flowas.genericcrud.service.impl;

import java.util.HashMap;
import java.util.Map;

import net.flowas.genericcrud.CrudType;
import net.flowas.genericcrud.ExecuteContext;
import net.flowas.genericcrud.dto.QueryOption;
import net.flowas.genericcrud.service.chain.ExecuteHandler;
import net.flowas.genericcrud.service.chain.ProcesserRegister;

public class RequestDispatcher {
	private final Map<Class, ExecuteHandler> handlerSet = new HashMap<>();
	private final Map<String, Class> typeMaps = new HashMap<>();
	private ProcesserRegister processerRegister;
	public void setProcesserRegister(ProcesserRegister processerRegister) {
		this.processerRegister = processerRegister;
	}
	public Object hangleRequest(String modelType, CrudType count, QueryOption option) {
		return hangleRequest(getModelClass(modelType), count, option);
	}
	public Object singleItemProcess(String modelType, Long id, CrudType action) {
		return singleItemProcess(getModelClass(modelType), id, action);
	}
	public Object hangleRequest(Class type, CrudType action, QueryOption option) {
	    ExecuteContext req = new  ExecuteContext(type,action,option);	    
		processerRegister.preProcess(req);		
		findHandler(type).handleRequest(req);
		processerRegister.postProcess(req);
		return req.getResult();
	}
	public Object singleItemProcess(Class modelType, Long id,CrudType action) {
		QueryOption<Long> option= new QueryOption<>();
	    option.setExample(id);
	    return hangleRequest(modelType,action,option);
	}
	
	/**
	   * 注册仓库的处理能力,主要是将自身能处理的类型注册给核心模块.
	   * @param handler 仓库处理实现
	   */
	  public void registHandler(ExecuteHandler handler) {
	    for (Class cls : handler.getHandledTypes()) {
	      typeMaps.put(cls.getSimpleName(), cls);
	      handlerSet.put(cls, handler);
	    }
	  }

	  private ExecuteHandler findHandler(Class modelClass) {
		ExecuteHandler handler = handlerSet.get(modelClass);
	    if(handler==null) {
	      throw new IllegalArgumentException("Entity type '" + modelClass.getSimpleName() + "' can not found!");
	    }
	    return handler;
	  }
	  
	
	 public Map<String, Class> getTypeMaps() {
		 return typeMaps; 
	 }
	 
	 public Class getModelClass(String modelType) {
		 Class clasz = typeMaps.get(modelType);
		 if(clasz==null) {
			 throw new IllegalStateException("model type of ["+modelType+"] is not registered!");
		 }
		 return clasz;
	 }	
}
